/*
 * Copyright 2011 Drew Wilder-Goodwin
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "resources.h"
#include "globals.h"
#include "input_tab.h"
#include "main_dialog.h"
#include "utility.h"
#include <assert.h>
#include <commctrl.h>
#include <stdio.h>
#include <wchar.h>
#include <winuser.h>

INT_PTR CALLBACK InputTabDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    return FALSE;
}

VOID create_input_tab(Tab *tab)
{
    HWND hInputTabDialog;
    
    /* Create sound dialog */
    hInputTabDialog = CreateDialogW(g_hinstance, MAKEINTRESOURCEW(DLG_INPUT),
        g_hmaindialog, InputTabDialogProc);
    tab_initialize(tab, hInputTabDialog, NULL);
    if (hInputTabDialog == NULL) {
        MessageBoxA(g_hmaindialog, "Input tab could not be created", "Fatal error",
            MB_OK | MB_ICONINFORMATION);
    }
    
    /* Populate strings and resize */
    PopulateInputTabLabels(hInputTabDialog);
    PopulateInputTabValues(hInputTabDialog);
}

VOID PopulateInputTabLabels(HWND hInputTabDialog)
{
    HWND hList;
    WCHAR *text;
    LVCOLUMNW lvc;
    
    hList = GetDlgItem(hInputTabDialog, DLG_INP_DID_LV);

    /* Groupboxes */
    set_control_text_resource(hInputTabDialog,
    		STRING_DLG_INP_DID_GB, DLG_INP_DID_GB);
    set_control_text_resource(hInputTabDialog,
    		STRING_DLG_INP_IRD_GB, DLG_INP_IRD_GB);
    set_control_text_resource(hInputTabDialog,
    		STRING_DLG_INP_NOTES_GB, DLG_INP_NOTES_GB);

    /* Listview Columns */
    lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
    lvc.cx = 100;


    LoadStringW(g_hinstance,STRING_DLG_INP_LV_DN,(WCHAR *)&text,0);
    lvc.iSubItem = 0;
    lvc.pszText = (LPWSTR)text;
    ListView_InsertColumnW(hList, 0, &lvc);

    LoadStringW(g_hinstance,STRING_DLG_INP_LV_STS,(WCHAR *)&text,0);
    lvc.iSubItem = 0;
    lvc.pszText = (LPWSTR)text;
    ListView_InsertColumnW(hList, 1, &lvc);

    LoadStringW(g_hinstance,STRING_DLG_INP_LV_CID,(WCHAR *)&text,0);
    lvc.iSubItem = 0;
    lvc.pszText = (LPWSTR)text;
    ListView_InsertColumnW(hList, 2, &lvc);

    LoadStringW(g_hinstance,STRING_DLG_INP_LV_VID,(WCHAR *)&text,0);
    lvc.iSubItem = 0;
    lvc.pszText = (LPWSTR)text;
    ListView_InsertColumnW(hList, 3, &lvc);

    LoadStringW(g_hinstance,STRING_DLG_INP_LV_PID,(WCHAR *)&text,0);
    lvc.iSubItem = 0;
    lvc.pszText = (LPWSTR)text;
    ListView_InsertColumnW(hList, 4, &lvc);

    LoadStringW(g_hinstance,STRING_DLG_INP_LV_FFD,(WCHAR *)&text,0);
    lvc.iSubItem = 0;
    lvc.pszText = (LPWSTR)text;
    ListView_InsertColumnW(hList, 5, &lvc);

}

VOID PopulateInputTabValues(HWND hInputTabDialog)
{

    int i, j;
    WCHAR attached[20];
    WCHAR *text;
    WCHAR *driver_name;
    WCHAR *driver_file_low;
    LPWSTR query = (LPWSTR)malloc(256 * sizeof(WCHAR));
    DxDiag_DirectInput *directInput;
    DxDiag_DirectInputDevice **directInputDevices;
    DxDiag_DirectInputRelatedDevice **directInputGamePorts;
    DxDiag_DirectInputRelatedDevice **directInputUSBs;
    DxDiag_DirectInputRelatedDevice **directInputPs2Devices;
    DxDiag_Driver **p_driver;
    TV_INSERTSTRUCTW tvinsert;
    HWND hTree, hList;
    HTREEITEM gamePorts, USBs, ps2Devices, item, subitem;
    

    directInput = g_dxdiagcom_root.directInput;
    
    directInputDevices = directInput->directInputDevices;
    directInputGamePorts = directInput->directInputGamePorts;
    directInputUSBs = directInput->directInputUSBs;
    directInputPs2Devices = directInput->directInputPs2Devices;
    /* Populate Tree */

    hTree = GetDlgItem(hInputTabDialog, DLG_INP_IRD_TREE);
    hList = GetDlgItem(hInputTabDialog, DLG_INP_DID_LV);

    /* check if input related devices exist */
    if(directInput->numDirectInputGamePorts == 0 && directInput->numDirectInputUSBs == 0
    && directInput->numDirectInputPs2Devices == 0){
        tvinsert.hParent=NULL;
        tvinsert.hInsertAfter=TVI_ROOT;
        tvinsert.item.mask=TVIF_TEXT;
        LoadStringW(g_hinstance,STRING_NA,(WCHAR *)&text,0);
        tvinsert.item.pszText=(LPWSTR)text;

        item = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);
    }

    /* check for GamePort devices */
    if(directInput->numDirectInputGamePorts != 0){
        tvinsert.hParent=NULL;
        tvinsert.hInsertAfter=TVI_ROOT;
        tvinsert.item.mask=TVIF_TEXT;
        LoadStringW(g_hinstance,STRING_SECTION_GAMEPORT_DEVICES,(WCHAR *)&text,0);
        tvinsert.item.pszText=(LPWSTR)text;

        gamePorts = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);

        for(i = 0; i < directInput->numDirectInputGamePorts; i++){
            tvinsert.hParent = gamePorts;
            tvinsert.hInsertAfter=TVI_FIRST;
            tvinsert.item.mask = TVIF_TEXT;
            tvinsert.item.pszText=(LPWSTR)(*directInputGamePorts[i]).szDescription;
	    /* insert device name */
	    item = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);

	    /* insert vendor and product id */
	    tvinsert.hParent = item;
            tvinsert.hInsertAfter=TVI_FIRST;
	    tvinsert.item.mask = TVIF_TEXT;
	    wsprintfW(query, L"Vendor/Product ID: 0x%X, 0x%X\n", (*directInputGamePorts[i]).dwVendorID, (*directInputGamePorts[i]).dwProductID);
	    tvinsert.item.pszText=query;
            subitem = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);

 	    /* insert matching device ID */
	    tvinsert.hParent = item;
	    tvinsert.hInsertAfter=TVI_FIRST;
	    tvinsert.item.mask = TVIF_TEXT;
	    wsprintfW(query, "Matching Device ID: %s\n", (*directInputGamePorts[i]).szMatchingDeviceId);
	    tvinsert.item.pszText=query;
	    subitem = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);

	    /* insert upper filters */
	    tvinsert.hParent = item;
	    tvinsert.hInsertAfter=TVI_FIRST;
	    tvinsert.item.mask = TVIF_TEXT;
	    wsprintfW(text, "Upper Filters: %s\n", (*directInputGamePorts[i]).szUpperFilters);
	    tvinsert.item.pszText=text;
	    subitem = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);

	    /* insert service name */
	    tvinsert.hParent = item;
	    tvinsert.hInsertAfter=TVI_FIRST;
	    tvinsert.item.mask = TVIF_TEXT;
	    wsprintfW(query, "Service: %s\n", (*directInputGamePorts[i]).szService);
	    tvinsert.item.pszText=query;
	    subitem = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);

	    /* insert Driver info */
	    tvinsert.hParent = item;
	    tvinsert.hInsertAfter=TVI_FIRST;
	    tvinsert.item.mask = TVIF_TEXT;
	    for(j = 0; j < (**directInputGamePorts).numDrivers; j++){
                p_driver = (*directInputGamePorts[i]).drivers;
                driver_name = (*p_driver[j]).szName;
                driver_file_low = (*p_driver[j]).dwFileTimeLow;
	        wsprintfW(query, "Driver: %s, %s\n", driver_name, driver_file_low);
	        tvinsert.item.pszText=query;
	        subitem = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);
	    }
        }

    }

    /* check for USB devices */
    if(directInput->numDirectInputUSBs != 0){
        tvinsert.hParent=NULL;
        tvinsert.hInsertAfter=TVI_ROOT;
        tvinsert.item.mask=TVIF_TEXT;
        LoadStringW(g_hinstance,STRING_SECTION_USB_DEVICES,(WCHAR *)&text,0);
        tvinsert.item.pszText=(LPWSTR)text;
        USBs = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);


        for(i = 0; i < directInput->numDirectInputUSBs; i++){
            tvinsert.hParent = USBs;
            tvinsert.hInsertAfter=TVI_FIRST;
            tvinsert.item.mask = TVIF_TEXT;
            tvinsert.item.pszText=(LPWSTR)(*directInputUSBs[i]).szDescription;
	    /* insert device name */
	    USBs = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);

            /* insert vendor and product id */
	    tvinsert.hParent = item;
            tvinsert.hInsertAfter=TVI_FIRST;
	    tvinsert.item.mask = TVIF_TEXT;
	    wsprintfW(query, L"Vendor/Product ID: 0x%X, 0x%X\n", (*directInputUSBs[i]).dwVendorID, (*directInputUSBs[i]).dwProductID);
	    tvinsert.item.pszText=query;
            subitem = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);

 	    /* insert matching device ID */
	    tvinsert.hParent = item;
	    tvinsert.hInsertAfter=TVI_FIRST;
	    tvinsert.item.mask = TVIF_TEXT;
	    wsprintfW(query, "Matching Device ID: %s\n", (*directInputUSBs[i]).szMatchingDeviceId);
	    tvinsert.item.pszText=query;
	    subitem = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);

	    /* insert upper filters */
	    tvinsert.hParent = item;
	    tvinsert.hInsertAfter=TVI_FIRST;
	    tvinsert.item.mask = TVIF_TEXT;
	    wsprintfW(query, "Upper Filters: %s\n", (*directInputUSBs[i]).szUpperFilters);
	    tvinsert.item.pszText=query;
	    subitem = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);

	    /* insert service name */
	    tvinsert.hParent = item;
	    tvinsert.hInsertAfter=TVI_FIRST;
	    tvinsert.item.mask = TVIF_TEXT;
	    wsprintfW(query, "Service: %s\n", (*directInputUSBs[i]).szService);
	    tvinsert.item.pszText=query;
	    subitem = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);

	    /* insert Driver info */
	    tvinsert.hParent = item;
	    tvinsert.hInsertAfter=TVI_FIRST;
	    tvinsert.item.mask = TVIF_TEXT;
	    for(j = 0; j < (**directInputUSBs).numDrivers; j++){
                p_driver = (*directInputUSBs[i]).drivers;
                driver_name = (*p_driver[j]).szName;
                driver_file_low = (*p_driver[j]).dwFileTimeLow;
	        wsprintfW(query, "Driver: %s, %s\n", driver_name, driver_file_low);
	        tvinsert.item.pszText=query;
	        subitem = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);
	    }
        }

    }

    /* check for PS/2 Devices */
    if(directInput->numDirectInputPs2Devices){
        tvinsert.hParent=NULL;
        tvinsert.hInsertAfter=TVI_ROOT;
        tvinsert.item.mask=TVIF_TEXT;
        LoadStringW(g_hinstance,STRING_SECTION_PS2_DEVICES,(WCHAR *)&text,0);
        tvinsert.item.pszText=(LPWSTR)text;
	 
        ps2Devices = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);


        for(i = 0; i < directInput->numDirectInputPs2Devices; i++){
            tvinsert.hParent = ps2Devices;
            tvinsert.hInsertAfter=TVI_FIRST;
            tvinsert.item.mask = TVIF_TEXT;
            tvinsert.item.pszText=(LPWSTR)(*directInputPs2Devices[i]).szDescription;
	    /*insert device name */
	    ps2Devices = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);

	    /* insert vendor and product id */
	    tvinsert.hParent = item;
            tvinsert.hInsertAfter=TVI_FIRST;
	    tvinsert.item.mask = TVIF_TEXT;
	    wsprintfW(query, L"Vendor/Product ID: 0x%X, 0x%X\n", (*directInputPs2Devices[i]).dwVendorID, (*directInputPs2Devices[i]).dwProductID);
	    tvinsert.item.pszText=query;
            subitem = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);

 	    /* insert matching device ID */
	    tvinsert.hParent = item;
	    tvinsert.hInsertAfter=TVI_FIRST;
	    tvinsert.item.mask = TVIF_TEXT;
	    wsprintfW(query, "Matching Device ID: %s\n", (*directInputPs2Devices[i]).szMatchingDeviceId);
	    tvinsert.item.pszText=query;
	    subitem = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);

	    /* insert upper filters */
	    tvinsert.hParent = item;
	    tvinsert.hInsertAfter=TVI_FIRST;
	    tvinsert.item.mask = TVIF_TEXT;
	    wsprintfW(query, "Upper Filters: %s\n", (*directInputPs2Devices[i]).szUpperFilters);
	    tvinsert.item.pszText=query;
	    subitem = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);

	    /* insert service name */
	    tvinsert.hParent = item;
	    tvinsert.hInsertAfter=TVI_FIRST;
	    tvinsert.item.mask = TVIF_TEXT;
	    wsprintfW(query, "Service: %s\n", (*directInputPs2Devices[i]).szService);
	    tvinsert.item.pszText=query;
	    subitem = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);

	    /* insert Driver info */
	    tvinsert.hParent = item;
	    tvinsert.hInsertAfter=TVI_FIRST;
	    tvinsert.item.mask = TVIF_TEXT;
	    for(j = 0; j < (**directInputPs2Devices).numDrivers; j++){
                p_driver = (*directInputPs2Devices[i]).drivers;
                driver_name = (*p_driver[j]).szName;
                driver_file_low = (*p_driver[j]).dwFileTimeLow;
	        wsprintfW(query, "Driver: %s, %s\n", driver_name, driver_file_low);
	        tvinsert.item.pszText=query;
	        subitem = (HTREEITEM)TreeView_InsertItemW(hTree,&tvinsert);
	    }
        }

    }

    /* Populate Listview */
    for(i = 0; i < directInput->numDirectInputDevices; i++)
    {
        LVITEMW lvi;
        int result;
        lvi.mask = LVIF_TEXT;
        lvi.state = 0;
        lvi.stateMask = 0;
        lvi.iItem = i;
        lvi.iSubItem = 0;
        lvi.lParam = (LPARAM) 0;
        lvi.pszText = (LPWSTR)(*directInputDevices[i]).szInstanceName;
        result = ListView_InsertItemW(hList, &lvi);

        if(lstrcmpW((*directInputDevices[i]).bAttached, L"True") == 0)
        {
            attached[0] = 'A'; attached[1] = 't'; attached[2] = 't'; attached[3] = 'a';
            attached[4] = 'c'; attached[5] = 'h'; attached[6] = 'e'; attached[7] = 'd';
            attached[8] = '\0';
        }
        else
        {
            attached[0] = 'N'; attached[1] = 'o'; attached[2] = 't'; attached[3] = ' ';
            attached[4] = 'A'; attached[5] = 't'; attached[6] = 't'; attached[7] = 'a';
            attached[8] = 'c'; attached[9] = 'h'; attached[10] = 'e'; attached[11] = 'd';
            attached[12] = '\0';
        }
        ListView_SetItemTextW(hList, i, 1, (LPWSTR) attached);
        ListView_SetItemTextW(hList, i, 2, (LPWSTR)(*directInputDevices[i]).dwJoystickID);
        ListView_SetItemTextW(hList, i, 3, (LPWSTR)(*directInputDevices[i]).dwVendorID);
        ListView_SetItemTextW(hList, i, 4, (LPWSTR)(*directInputDevices[i]).dwProductID);
        ListView_SetItemTextW(hList, i, 5, (LPWSTR)(*directInputDevices[i]).szFFDriverName);
    
    }
    /* Notes information */
    set_control_text(hInputTabDialog, (WCHAR *)directInput->szInputNotesLocalized, DLG_INP_NOTES);
}
